feat: add PS/2 keyboard interrupt driver#2532
Conversation
7c21b3f to
5d35a06
Compare
There was a problem hiding this comment.
Benchmark Results
Details
| Benchmark | Current: f6c859b | Previous: b3883fa | Performance Ratio |
|---|---|---|---|
| startup_benchmark Build Time | 80.43 s |
80.39 s |
1.00 ❗ |
| startup_benchmark File Size | 0.79 MB |
0.79 MB |
1.00 ❗ |
| Startup Time - 1 core | 0.74 s (±0.02 s) |
0.74 s (±0.01 s) |
0.99 |
| Startup Time - 2 cores | 0.75 s (±0.02 s) |
0.75 s (±0.02 s) |
1.00 |
| Startup Time - 4 cores | 0.74 s (±0.02 s) |
0.76 s (±0.02 s) |
0.98 |
| multithreaded_benchmark Build Time | 78.14 s |
83.71 s |
0.93 ❗ |
| multithreaded_benchmark File Size | 0.90 MB |
0.90 MB |
1.00 ❗ |
| Multithreaded Pi Efficiency - 2 Threads | 91.24 % (±6.29 %) |
87.67 % (±5.37 %) |
1.04 |
| Multithreaded Pi Efficiency - 4 Threads | 44.09 % (±3.01 %) |
43.34 % (±2.79 %) |
1.02 |
| Multithreaded Pi Efficiency - 8 Threads | 25.97 % (±1.36 %) |
25.32 % (±1.83 %) |
1.03 |
| micro_benchmarks Build Time | 77.31 s |
80.38 s |
0.96 ❗ |
| micro_benchmarks File Size | 0.90 MB |
0.90 MB |
1.00 ❗ |
| Scheduling time - 1 thread | 64.87 ticks (±1.95 ticks) |
68.25 ticks (±5.81 ticks) |
0.95 |
| Scheduling time - 2 threads | 35.83 ticks (±4.52 ticks) |
38.15 ticks (±5.34 ticks) |
0.94 |
| Micro - Time for syscall (getpid) | 4.31 ticks (±0.68 ticks) |
4.13 ticks (±0.69 ticks) |
1.05 |
| Memcpy speed - (built_in) block size 4096 | 84909.85 MByte/s (±58667.15 MByte/s) |
82192.20 MByte/s (±56877.97 MByte/s) |
1.03 |
| Memcpy speed - (built_in) block size 1048576 | 30612.01 MByte/s (±24660.72 MByte/s) |
30409.95 MByte/s (±24564.57 MByte/s) |
1.01 |
| Memcpy speed - (built_in) block size 16777216 | 29334.73 MByte/s (±24120.88 MByte/s) |
26462.68 MByte/s (±21974.68 MByte/s) |
1.11 |
| Memset speed - (built_in) block size 4096 | 85374.66 MByte/s (±58982.93 MByte/s) |
82271.23 MByte/s (±56937.12 MByte/s) |
1.04 |
| Memset speed - (built_in) block size 1048576 | 31379.42 MByte/s (±25114.87 MByte/s) |
31147.37 MByte/s (±25005.00 MByte/s) |
1.01 |
| Memset speed - (built_in) block size 16777216 | 30110.51 MByte/s (±24574.49 MByte/s) |
27241.00 MByte/s (±22475.91 MByte/s) |
1.11 |
| Memcpy speed - (rust) block size 4096 | 75734.61 MByte/s (±52842.48 MByte/s) |
74974.37 MByte/s (±52256.45 MByte/s) |
1.01 |
| Memcpy speed - (rust) block size 1048576 | 30314.32 MByte/s (±24509.72 MByte/s) |
30241.00 MByte/s (±24501.06 MByte/s) |
1.00 |
| Memcpy speed - (rust) block size 16777216 | 29430.51 MByte/s (±24217.05 MByte/s) |
27430.85 MByte/s (±22631.84 MByte/s) |
1.07 |
| Memset speed - (rust) block size 4096 | 76210.80 MByte/s (±53189.43 MByte/s) |
75374.74 MByte/s (±52547.87 MByte/s) |
1.01 |
| Memset speed - (rust) block size 1048576 | 31078.99 MByte/s (±24965.20 MByte/s) |
30996.28 MByte/s (±24944.22 MByte/s) |
1.00 |
| Memset speed - (rust) block size 16777216 | 30218.81 MByte/s (±24682.21 MByte/s) |
28210.43 MByte/s (±23118.03 MByte/s) |
1.07 |
| alloc_benchmarks Build Time | 76.26 s |
76.93 s |
0.99 ❗ |
| alloc_benchmarks File Size | 0.87 MB |
0.87 MB |
1.00 ❗ |
| Allocations - Allocation success | 91.31 % |
91.31 % |
1 |
| Allocations - Deallocation success | 100.00 % |
100.00 % |
1 |
| Allocations - Pre-fail Allocations | 61.44 % |
61.44 % |
1 |
| Allocations - Average Allocation time | 5077.51 Ticks (±103.05 Ticks) |
5120.57 Ticks (±121.11 Ticks) |
0.99 |
| Allocations - Average Allocation time (no fail) | 5832.75 Ticks (±108.42 Ticks) |
5812.28 Ticks (±133.21 Ticks) |
1.00 |
| Allocations - Average Deallocation time | 1294.70 Ticks (±142.42 Ticks) |
1001.83 Ticks (±184.72 Ticks) |
1.29 ❗ |
| mutex_benchmark Build Time | 75.95 s |
77.85 s |
0.98 ❗ |
| mutex_benchmark File Size | 0.90 MB |
0.90 MB |
1.00 ❗ |
| Mutex Stress Test Average Time per Iteration - 1 Threads | 12.24 ns (±0.68 ns) |
12.44 ns (±0.61 ns) |
0.98 |
| Mutex Stress Test Average Time per Iteration - 2 Threads | 41.90 ns (±2.26 ns) |
44.68 ns (±3.31 ns) |
0.94 |
This comment was automatically generated by workflow using github-action-benchmark.
5d35a06 to
2c424d5
Compare
2c424d5 to
f6c859b
Compare
mkroening
left a comment
There was a problem hiding this comment.
Thanks for the PR! :)
I was wondering why implement drivers for legacy devices instead of USB keyboards (xhci, usb-oxide, embassy-usb). I guess it is because of simplicity.
It would be great to discuss the high-level application-facing API, since that is the hardest to change once merged.
| "dhcpv4", | ||
| "fsgsbase", | ||
| "kernel-stack", | ||
| "keyboard", |
There was a problem hiding this comment.
I don't think this should be a default feature.
| ## Enables the PS/2 keyboard driver. | ||
| ## | ||
| ## This is only useful on PCs (x86-64). | ||
| keyboard = [] |
There was a problem hiding this comment.
Could you rename this to pc-keyboard? Also, please make sure that the docs don't imply that this is needed for keyboard support in general. Serial-based keyboard support is separate from this. Similar to the framebuffer, please also put a disclaimer that this does not make the kernel use the driver and instead exposes an API for applications that need to be ported.
| #[cfg(not(all(target_arch = "x86_64", feature = "keyboard")))] | ||
| #[hermit_macro::system] | ||
| #[unsafe(no_mangle)] | ||
| pub extern "C" fn sys_read_keyboard() -> u8 { | ||
| 0 | ||
| } |
There was a problem hiding this comment.
Similar to the framebuffer PR, please either merge the function definitions or (preferrably) just remove the symbol when the feature is disabled.
| } | ||
|
|
||
| pub(crate) fn install_handlers(handlers: InterruptHandlerMap) { | ||
| pub(crate) fn install_handlers(#[allow(unused_mut)] mut handlers: InterruptHandlerMap) { |
There was a problem hiding this comment.
Please move the allow to the function level instead of having it inline like this.
| pub(crate) fn install_handlers(#[allow(unused_mut)] mut handlers: InterruptHandlerMap) { | ||
| #[cfg(feature = "keyboard")] | ||
| { | ||
| use crate::arch::kernel::keyboard::get_keyboard_handler; |
There was a problem hiding this comment.
| use crate::arch::kernel::keyboard::get_keyboard_handler; | |
| use crate::arch::kernel::keyboard::get_keyboard_handler; | |
| data_port.write(config); | ||
| cmd_port.write(PS2_CMD_ENABLE_KEYBOARD); | ||
| } | ||
| fn keyboard_handler() { |
There was a problem hiding this comment.
Please move the handler to the top level outside of this function.
| while (cmd_port.read() & PS2_BUFFER_FULL) != 0 { | ||
| let _ = data_port.read(); | ||
| } |
There was a problem hiding this comment.
Why do we discard the device buffer instead of filling our read buffer?
| let mut cmd_port = Port::<u8>::new(PS2_CMD_PORT); | ||
| let mut data_port = Port::<u8>::new(PS2_DATA_PORT); |
There was a problem hiding this comment.
Do you think an abstraction similar to the proposal for BGA would make sense?
struct Ps2;
impl Ps2 {
fn read_data() -> u8;
fn write_data(data: u8);
fn status() -> u8;
fn command(command: u8);
}| /// Pops a scancode from the keyboard buffer, returning None if the buffer is empty. | ||
| pub fn pop_scancode() -> Option<u8> { |
There was a problem hiding this comment.
A scancode can never be zero, right? Returning Option<NonZero<u8>> would be preferable in that case.
| #[cfg(all(target_arch = "x86_64", feature = "keyboard"))] | ||
| #[hermit_macro::system] | ||
| #[unsafe(no_mangle)] | ||
| pub extern "C" fn sys_read_keyboard() -> u8 { | ||
| crate::kernel::keyboard::pop_scancode().unwrap_or(0) | ||
| } |
There was a problem hiding this comment.
I am not too sure about this API. Is the application supposed to busy loop on this and retrieve one event at a time?
What about doing something similar to Linux's event device (evdev) interface (Linux docs)? Reading from /dev/input/event0 would then fill a user buffer with input events and blocks if no events are there unless opened with O_NONBLOCK.
This feature adds support for the PS2 legacy keyboard in Qemu x86_64.
Currently it does:
The systemcall returns 0 if the keyboard feature is disabled.
I have only tested this feature with C programs on a Mac using Qemu.